using System;
using DevExpress.Xpo.DB.Exceptions;
using NUnit.Framework;
using SmartPeople.Framework.SecuritySpace;
using SmartPeople.Framework.SecuritySpace.Tests;

namespace SmartPeople.Framework.SecuritySpace.Provider.Tests
{
    [TestFixture]
    public class SecurityRoleTests
    {

        //SecApp_001
        [Test, Description("Create a security application")]
        public void ApplicationRoles()
        {
            ISecuritySpace securitySpaceHRMS = TestsHelper.GetSecuritySpace("HRMS");
            securitySpaceHRMS.Clear();

            ISecuritySpace securitySpaceCRM = TestsHelper.GetSecuritySpace("CRM");
            securitySpaceCRM.Clear();

            securitySpaceHRMS.Roles.CreateRole(TestRoles.Operators);
            Assert.AreEqual(1, securitySpaceHRMS.Roles.Count);
            Assert.AreEqual(0, securitySpaceCRM.Roles.Count);
            Assert.IsTrue(securitySpaceHRMS.Roles.RoleExists(TestRoles.Operators));
            Assert.IsFalse(securitySpaceCRM.Roles.RoleExists(TestRoles.Operators));
            securitySpaceCRM.Roles.CreateRole(TestRoles.Administrators);
            securitySpaceCRM.Roles.CreateRole(TestRoles.Operators);
            Assert.AreEqual(1, securitySpaceHRMS.Roles.Count);
            Assert.AreEqual(2, securitySpaceCRM.Roles.Count);
            securitySpaceHRMS.Roles.DeleteRole(TestRoles.Operators);
            Assert.AreEqual(0, securitySpaceHRMS.Roles.Count);
            Assert.AreEqual(2, securitySpaceCRM.Roles.Count);
            Assert.IsFalse(securitySpaceHRMS.Roles.RoleExists(TestRoles.Administrators));
            Assert.IsTrue(securitySpaceCRM.Roles.RoleExists(TestRoles.Administrators));

            securitySpaceCRM.Clear();
            securitySpaceHRMS.Clear();
        }


        /// SRole_001
        [Test, Description("Creates a Role,deletes the created role.")]
        public void CreateARole()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            //clear security space
            securitySpace.Clear();

            //create role
            ISecurityRole role1 = securitySpace.Roles.CreateRole(TestRoles.Operators);
            //check role not null
            Assert.IsNotNull(role1);
            //check roles are same
            Assert.AreEqual(TestRoles.Operators, securitySpace.Roles.GetRole(TestRoles.Operators).Name);
            //confirm role exists
            Assert.IsTrue(securitySpace.Roles.RoleExists(TestRoles.Operators));
            //delete role
            securitySpace.Roles.DeleteRole(TestRoles.Operators);
            //check if role is deleted
            Assert.IsFalse(securitySpace.Roles.RoleExists(TestRoles.Operators));

            securitySpace.Clear();
        }


        // SRole_002
        [Test, Description("Create Duplicate Role Error")]
        public void ErrorOnCreateDuplicateRole()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            //create one operator role
            securitySpace.Roles.CreateRole(TestRoles.Operators);
            //check if the next role which is same give the constrain violation
            MyAssert.ExpectedException(typeof (ConstraintViolationException),
                                       delegate { securitySpace.Roles.CreateRole(TestRoles.Operators); },
                                       "Create Duplicate Role with same name should fail!");

            securitySpace.Clear();
        }


        /// SRole_003
        [Test, Description("Creates a role and assigns to two user and then deletes the role")]
        public void DeleteApplicationRoles()
        {
            ISecuritySpace securitySpaceHRMS = TestsHelper.GetSecuritySpace("HRMS");
            securitySpaceHRMS.Clear();

            //create an operator role
            securitySpaceHRMS.Roles.CreateRole(TestRoles.Operators);
            //create a user
            ISecurityUser user1 = securitySpaceHRMS.Users.CreateUser(TestUsers.User1, "user1srole003@acme.com");

            string[] roleNames = new string[] {TestRoles.Operators};
            string[] userNames = new string[] {user1.UserName};
            //add usernames to roles
            securitySpaceHRMS.Roles.AddUsersToRoles(userNames, roleNames);
            //check if roles and users added
            Assert.AreEqual(1, securitySpaceHRMS.Roles.Count);
            Assert.AreEqual(1, securitySpaceHRMS.Users.Count);

            securitySpaceHRMS.Roles.DeleteRole(TestRoles.Operators);
            Assert.AreEqual(0, securitySpaceHRMS.Roles.Count);
            Assert.AreEqual(1, securitySpaceHRMS.Users.Count);

            securitySpaceHRMS.Users.DeleteUser("User1");

            securitySpaceHRMS.Clear();
        }




        [Test, Description("If throwOnPopulatedRole is true,and if there are users assigned to the roles then exception should be thrown")]
        public void DeleteRoleWithThrowOnPopulatedRole()
        {
            ISecuritySpace securitySpaceHRMS = TestsHelper.GetSecuritySpace("HRMS");
            securitySpaceHRMS.Clear();

            //create an operator role
            securitySpaceHRMS.Roles.CreateRole(TestRoles.Operators);
            //create a user
            ISecurityUser user1 = securitySpaceHRMS.Users.CreateUser(TestUsers.User1, "user1srole003@acme.com");

            string[] roleNames = new string[] { TestRoles.Operators };
            string[] userNames = new string[] { user1.UserName };
            //add usernames to roles
            securitySpaceHRMS.Roles.AddUsersToRoles(userNames, roleNames);
            //check if roles and users added
            Assert.AreEqual(1, securitySpaceHRMS.Roles.Count);
            Assert.AreEqual(1, securitySpaceHRMS.Users.Count);

            MyAssert.ExpectedException(typeof(ArgumentException),
                           delegate { securitySpaceHRMS.Roles.DeleteRole(TestRoles.Operators, true); },
                           "Deleting role with users and throwOnPopulatedRole true should fail!");


            //Assert.AreEqual(0, securitySpaceHRMS.Roles.Count);
            //Assert.AreEqual(1, securitySpaceHRMS.Users.Count);

            securitySpaceHRMS.Users.DeleteUser("User1");

            securitySpaceHRMS.Clear();
            
        }

        /// SRole_004
        [Test, Description("Check IsUserInRole")]
        public void IsUserInRole()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            //create two roles
            securitySpace.Roles.CreateRole(TestRoles.Administrators);
            securitySpace.Roles.CreateRole(TestRoles.Operators);
            //create three users
            securitySpace.Users.CreateUser(TestUsers.Administrator, "srolead04@acme.com");
            securitySpace.Users.CreateUser(TestUsers.User1, "srolesuser1004@acme.com");
            securitySpace.Users.CreateUser(TestUsers.User2, "srolesuser0042@acme.com");
            //confirm that the first two users are not in role administrator
            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.Administrator, TestRoles.Administrators));
            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.User1, TestRoles.Administrators));
            //confirm that the user1 and user 2 are not in role operator
            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.User1, TestRoles.Operators));
            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.User2, TestRoles.Operators));

            securitySpace.Roles.AddUsersToRoles(new string[] {TestUsers.Administrator, TestUsers.User1},
                                                new string[] {TestRoles.Administrators});
            securitySpace.Roles.AddUsersToRoles(new string[] {TestUsers.User1, TestUsers.User2},
                                                new string[] {TestRoles.Operators});

            Assert.IsTrue(securitySpace.Roles.IsUserInRole(TestUsers.Administrator, TestRoles.Administrators));
            Assert.IsTrue(securitySpace.Roles.IsUserInRole(TestUsers.User1, TestRoles.Administrators));
            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.User2, TestRoles.Administrators));

            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.Administrator, TestRoles.Operators));
            Assert.IsTrue(securitySpace.Roles.IsUserInRole(TestUsers.User1, TestRoles.Operators));
            Assert.IsTrue(securitySpace.Roles.IsUserInRole(TestUsers.User2, TestRoles.Operators));

            //Remove User1 from Administrators then do checks.
            securitySpace.Roles.RemoveUsersFromRoles(new string[] {TestUsers.User1},
                                                     new string[] {TestRoles.Administrators});
            Assert.IsTrue(securitySpace.Roles.IsUserInRole(TestUsers.Administrator, TestRoles.Administrators));
            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.User1, TestRoles.Administrators));
            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.User2, TestRoles.Administrators));
            Assert.IsFalse(securitySpace.Roles.IsUserInRole(TestUsers.Administrator, TestRoles.Operators));
            Assert.IsTrue(securitySpace.Roles.IsUserInRole(TestUsers.User1, TestRoles.Operators));
            Assert.IsTrue(securitySpace.Roles.IsUserInRole(TestUsers.User2, TestRoles.Operators));

            securitySpace.Users.DeleteUser("User1");
            securitySpace.Users.DeleteUser("User2");

            securitySpace.Clear();
        }

        /// SRole_005
        [Test, Description("Remove a role assigned to a user without removing user")]
        public void RemoveRoleAssignedToUserWithoutRemovingUser()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            //create a role called operator
            securitySpace.Roles.CreateRole(TestRoles.Operators);

            //create a user
            securitySpace.Users.CreateUser(TestUsers.User1, TestUsers.User1Password, "srole005user1@acme.com");


            //add user to role
            string[] userNames = new string[] {TestUsers.User1, TestUsers.User2};
            securitySpace.Roles.AddUsersToRoles(userNames, new string[] {TestRoles.Operators});


            //check if user in role
            foreach (string userName in securitySpace.Roles.GetUsersInRole(TestRoles.Operators))
            {
                Assert.Contains(userName, userNames, "wrong usernames from GetUsersInRole!");
            }

            //check again
            Assert.AreEqual(1, securitySpace.Roles.GetUsersInRole(TestRoles.Operators).Length);


            MyAssert.ExpectedException(typeof (ArgumentException),
                                       delegate { securitySpace.Roles.DeleteRole(TestRoles.Operators, true); },
                                       "UserExists in Role! (This role is populated! throwOnPopulatedRole");

            securitySpace.Roles.DeleteRole(TestRoles.Operators, false);
            Assert.IsFalse(securitySpace.Roles.RoleExists(TestRoles.Operators));

            securitySpace.Users.DeleteUser("User1");
            securitySpace.Clear();
        }


        /// SRole_006
        [Test]
        public void RolesUsersUsingGUIDS()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            //clear security space
            securitySpace.Clear();
            string roleguid = "{D1C53875-43B4-4d3a-AB9C-BDB5A2354BDE}";
            //create role
            ISecurityRole role1 = securitySpace.Roles.CreateRole(new Guid(roleguid));
            //check role not null
            Assert.IsNotNull(role1);
            //check roles are same
            Assert.AreEqual(new Guid(roleguid), securitySpace.Roles.GetRole(new Guid(roleguid)).GID);
            //confirm role exists
            Assert.IsTrue(securitySpace.Roles.RoleExists(new Guid(roleguid)));
            string userguid = "{D9CA30B6-819A-4017-9A41-288DCF18536F}";
            securitySpace.Users.CreateUser(new Guid(userguid));
            Assert.AreEqual(1, securitySpace.Users.Count);
            Assert.AreEqual(1, securitySpace.Roles.Count);
            //delete role
            securitySpace.Roles.DeleteRole(TestRoles.Operators);
            //check if role is deleted
            Assert.IsFalse(securitySpace.Roles.RoleExists(TestRoles.Operators));
            securitySpace.Clear();
        }

        /// SRole_007
        [Test, Description("Adding/Removing Users to Roles using Names.")]
        public void RolesUsersUsingNames()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            TestRoles.CreateAllTestRoles(securitySpace);
            TestUsers.CreateAllTestUsers(securitySpace);

            string[] roleNames = new string[] {TestRoles.Administrators, TestRoles.Operators, TestRoles.Users};
            string[] userNames = new string[] {TestUsers.User1, TestUsers.User2, TestUsers.User3};

            securitySpace.Roles.AddUsersToRoles(userNames, roleNames);
            Assert.AreEqual(3, securitySpace.Roles.GetUsersInRole(TestRoles.Administrators).Length);
            Assert.AreEqual(3, securitySpace.Roles.GetUsersInRole(TestRoles.Operators).Length);
            Assert.AreEqual(3, securitySpace.Roles.GetUsersInRole(TestRoles.Users).Length);

            foreach (string userName in securitySpace.Roles.GetUsersInRole(TestRoles.Operators))
            {
                Assert.Contains(userName, userNames, "wrong usernames from GetUsersInRole!");
            }

            securitySpace.Roles.RemoveUsersFromRoles(new string[] {TestUsers.User1},
                                                     new string[] {TestRoles.Administrators});
            securitySpace.Roles.RemoveUsersFromRoles(new string[] {TestUsers.User1, TestUsers.User2},
                                                     new string[] {TestRoles.Operators});

            Assert.AreEqual(2, securitySpace.Roles.GetUsersInRole(TestRoles.Administrators).Length);
            Assert.AreEqual(1, securitySpace.Roles.GetUsersInRole(TestRoles.Operators).Length);
            Assert.AreEqual(3, securitySpace.Roles.GetUsersInRole(TestRoles.Users).Length);


            Assert.IsTrue(securitySpace.Roles.RoleExists(TestRoles.Operators));
            securitySpace.Roles.DeleteRole(TestRoles.Operators);

            Assert.IsFalse(securitySpace.Roles.RoleExists(TestRoles.Operators));
            securitySpace.Clear();
        }

        /// SRole_008
        [Test, Description("Remove a role assigned to a user after removing user")]
        public void RemoveUserRemoveRole()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Clear();

            securitySpace.Roles.CreateRole(TestRoles.Operators);
            securitySpace.Users.CreateUser(TestUsers.User1, "srole008user1@acme.com");
            securitySpace.Users.CreateUser(TestUsers.User2, "srole008user2@acme.com");

            securitySpace.Roles.AddUsersToRoles(new string[] {TestUsers.User1, TestUsers.User2},
                                                new string[] {TestRoles.Operators});
            securitySpace.Users.DeleteUser(TestUsers.User1);
            Assert.AreEqual(1, securitySpace.Roles.GetUsersInRole(TestRoles.Operators).Length);

            securitySpace.Roles.DeleteRole(TestRoles.Operators);
            Assert.IsFalse(securitySpace.Roles.RoleExists(TestRoles.Operators));

            securitySpace.Users.DeleteUser("User1");
            securitySpace.Users.DeleteUser("User2");
            securitySpace.Clear();
        }

        /// SRole_009
        [Test, Description("Create a role With RoleName numeric")]
        public void RoleNameNumeric()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Roles.Clear();

            MyAssert.ExpectedException(typeof (ArgumentException),
                                       delegate { securitySpace.Roles.CreateRole("123"); },
                                       "Role Name should be alpha character");

            securitySpace.Roles.Clear();
        }

        /// SRole_010
        [Test, Description("Create a role With RoleName Less Than Minimum Characters")]
        public void RoleNameLessThanMinChar()
        {
            ISecuritySpace securitySpace = TestsHelper.GetSecuritySpace();
            securitySpace.Roles.Clear();

            MyAssert.ExpectedException(typeof (ArgumentException),
                                       delegate { securitySpace.Roles.CreateRole("r"); },
                                       "Role Name should be more than single character");

            securitySpace.Roles.Clear();
        }
    }
}